import json
import requests

from fastapi import APIRouter, HTTPException, Header
from pydantic import BaseModel
from typing import Optional

from common.reset_machine import generate_machine_ids
from common.update_cursor_token import (
    TokenManager, CursorManager, CursorPatcher, Utils,
    FilePathManager, UpdateManager, TokenData, logger, FilePermissionManager
)

router = APIRouter(
    prefix="/cursor",
    tags=["cursor"],
    responses={404: {"description": "Not found"}},
)


class UpdateResponse(BaseModel):
    code: int = 200
    msg: str
    data: Optional[dict] = None


@router.post("/update", response_model=UpdateResponse)
async def update_cursor(authorization: str = Header(None)):
    """
    更新 Cursor Token
    """
    if not authorization:
        raise HTTPException(status_code=401, detail="无效的认证信息")

    try:
        # 获取Cursor路径
        pkg_path, main_path = FilePathManager.get_cursor_app_paths()
        if not Utils.check_files_exist(pkg_path, main_path):
            return UpdateResponse(code=400, msg="请检查是否正确安装 Cursor")

        # 检查版本
        cursor_version = json.loads(pkg_path.read_text(encoding="utf-8"))["version"]
        need_patch = CursorPatcher.check_version(cursor_version)

        # 获取新的 Token 数据
        headers = {
            "accept": "application/json",
            "Authorization": authorization
        }
        response = requests.get(
            "https://autotask.top/api/cursor/next-available",
            headers=headers
        )

        data = response.json()
        
        # 修改：检查使用限制的逻辑
        if data.get("code") == 403:
            return UpdateResponse(
                code=403,  # 直接返回403状态码
                msg=data.get("msg", "已达到使用限制"),
                data={"need_purchase": True}
            )

        if response.status_code != 200 or data.get("code") != 200:
            return UpdateResponse(
                code=400,
                msg=f"获取 Token 失败: {response.text}"
            )

        # 从响应中获取 account 和 token
        response_data = data["data"]
        token_data = TokenData.create_with_token(
            token=response_data["token"],
            email=response_data["account"]
        )

        # 退出 Cursor
        if not CursorManager.exit_cursor():
            return UpdateResponse(code=400, msg="退出 Cursor 失败")

        # 应用补丁（如果需要）
        if need_patch and not CursorPatcher.patch_main_js(main_path):
            return UpdateResponse(code=400, msg="Patch 失败")

        # 更新 Token
        if not TokenManager.update_token(token_data):
            return UpdateResponse(code=400, msg="更新 Token 失败")

        # 禁用自动更新
        UpdateManager.disable_auto_update_main()

        return UpdateResponse(
            code=200,
            msg="更新成功",
            data={
                "version": cursor_version,
                "need_patch": need_patch,
                "email": token_data.email,
                "token_info": {
                    "account": response_data["account"],
                    "token": response_data["token"],
                    "is_expired": response_data["is_expired"],
                    "remark": response_data["remark"]
                }
            }
        )

    except Exception as e:
        logger.error(f"更新过程中发生错误: {str(e)}", exc_info=True)
        return UpdateResponse(code=500, msg=f"更新过程中发生错误: {str(e)}")


@router.post("/patch", response_model=UpdateResponse)
async def patch_cursor():
    """
    仅执行 Cursor 补丁操作
    """
    try:
        # 获取Cursor路径
        pkg_path, main_path = FilePathManager.get_cursor_app_paths()

        if not Utils.check_files_exist(pkg_path, main_path):
            return UpdateResponse(
                code=400,
                msg="请检查是否正确安装 Cursor"
            )

        # 检查版本
        try:
            cursor_version = json.loads(pkg_path.read_text(encoding="utf-8"))["version"]
            need_patch = CursorPatcher.check_version(cursor_version)
        except Exception as e:
            return UpdateResponse(
                code=400,
                msg=f"读取版本信息失败: {str(e)}"
            )

        if not need_patch:
            return UpdateResponse(
                code=200,
                msg="当前版本无需补丁",
                data={"version": cursor_version}
            )

        # 退出Cursor
        if not CursorManager.exit_cursor():
            return UpdateResponse(
                code=400,
                msg="退出 Cursor 失败"
            )

        # 执行补丁
        if not CursorPatcher.patch_main_js(main_path):
            return UpdateResponse(
                code=400,
                msg="Patch 失败"
            )

        return UpdateResponse(
            code=200,
            msg="补丁应用成功",
            data={
                "version": cursor_version,
                "patched": True
            }
        )

    except Exception as e:
        return UpdateResponse(
            code=500,
            msg=f"补丁过程中发生错误: {str(e)}"
        )


@router.post("/disable-update", response_model=UpdateResponse)
async def disable_update():
    """
    仅禁用 Cursor 自动更新
    """
    try:
        # 先检查是否已经禁用
        if UpdateManager.is_update_disabled():
            return UpdateResponse(
                code=200,
                msg="自动更新已经处于禁用状态"
            )

        # 禁用自动更新
        if not UpdateManager.disable_auto_update_main():
            return UpdateResponse(
                code=400,
                msg="禁用自动更新失败"
            )

        return UpdateResponse(
            code=200,
            msg="已成功禁用自动更新"
        )

    except Exception as e:
        return UpdateResponse(
            code=500,
            msg=f"禁用更新过程中发生错误: {str(e)}"
        )


@router.post("/reset-machine-id")
async def reset_machine_id():
    """重置本机机器码"""
    try:
        # 获取存储路径
        storage_path = FilePathManager.get_storage_path()
        if not storage_path.exists():
            return UpdateResponse(code=400, msg="未找到Cursor配置文件")

        # 退出Cursor程序
        if not CursorManager.exit_cursor():
            return UpdateResponse(code=400, msg="退出Cursor失败")

        try:
            # 读取当前机器码
            FilePermissionManager.make_file_writable(storage_path)
            current_data = json.loads(storage_path.read_text(encoding='utf-8'))

            # 记录旧的机器码
            logger.info("当前机器码:")
            logger.info(f"macMachineId: {current_data.get('telemetry.macMachineId', 'N/A')}")
            logger.info(f"machineId: {current_data.get('telemetry.machineId', 'N/A')}")
            logger.info(f"devDeviceId: {current_data.get('telemetry.devDeviceId', 'N/A')}")
            logger.info(f"sqmId: {current_data.get('telemetry.sqmId', 'N/A')}")

            # 生成新的机器码
            new_ids = generate_machine_ids()

            # 更新机器码
            current_data.update(new_ids)

            # 记录新的机器码
            logger.info("新生成的机器码:")
            logger.info(f"macMachineId: {new_ids['telemetry.macMachineId']}")
            logger.info(f"machineId: {new_ids['telemetry.machineId']}")
            logger.info(f"devDeviceId: {new_ids['telemetry.devDeviceId']}")
            logger.info(f"sqmId: {new_ids['telemetry.sqmId']}")

            # 保存更新后的配置
            storage_path.write_text(json.dumps(current_data, indent=4))
            FilePermissionManager.make_file_readonly(storage_path)

            return UpdateResponse(
                code=200,
                msg="机器码重置成功",
                data={
                    "old_ids": {
                        "macMachineId": current_data.get('telemetry.macMachineId'),
                        "machineId": current_data.get('telemetry.machineId'),
                        "devDeviceId": current_data.get('telemetry.devDeviceId'),
                        "sqmId": current_data.get('telemetry.sqmId')
                    },
                    "new_ids": new_ids
                }
            )

        except Exception as e:
            logger.error(f"重置机器码时发生错误: {str(e)}")
            return UpdateResponse(code=500, msg=f"重置机器码失败: {str(e)}")

        finally:
            # 确保文件恢复只读状态
            FilePermissionManager.make_file_readonly(storage_path)

    except Exception as e:
        logger.error(f"重置机器码过程中发生错误: {str(e)}", exc_info=True)
        return UpdateResponse(code=500, msg=f"操作失败: {str(e)}")
